package com.onesports.intelligent.k12.polarlight.util;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * author:pengkaijuan
 * Date:2018/9/29 21:17
 * Desc:
 */
public class HttpUtil {
    /**
     * 发起get请求
     * <p>
     * 替换ACCESS_TOKEN，访问凭证过期时，重新获取凭证并发起原有调用
     */

    public static String doGet(String accessToken, String url) {
        String realUrl = url.replace("ACCESS_TOKEN", accessToken);
        String rs = executeGet(realUrl);

        //JSONObject json = JSONObject.fromObject(rs);
        // 访问凭证失效时，重新进行一次获取凭证并发起原来业务调用
		/*if (json.containsKey("errcode")
				&& (json.getInt("errcode") == 40001
				|| json.getInt("errcode") == 40014
				|| json.getInt("errcode") == 41001
				|| json.getInt("errcode") == 42001)) {
			realUrl = url.replace("ACCESS_TOKEN",accessToken);
			rs = executeGet(realUrl);
		}*/
        return rs;
    }

    /**
     * access_token 接口直接调用，其它调用doGet
     */
    public static String executeGet(String url) {
        try {
            HttpGet httpGet = new HttpGet(url);
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(httpGet);
            String resultContent = new Utf8ResponseHandler()
                    .handleResponse(response);
            System.out.println("result=" + resultContent);
            return resultContent;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 发起post请求
     * <p>
     * 替换ACCESS_TOKEN，访问凭证过期时，重新获取凭证并发起原有调用
     */
    public static String doPost(String accessToken, String url, String body) {
        String realUrl = url.replace("ACCESS_TOKEN", accessToken);//url放入获取的accessToken
        String rs = executePost(realUrl, body);//调用方法
        return rs;
    }

    public static String executePost(String url, String body) {
        try {
            HttpPost httpPost = new HttpPost(url);//httpPost请求
            StringEntity entity = new StringEntity(body, "UTF-8");//转换成字符串
            entity.setContentType("application/json;charset=utf-8");
            httpPost.setEntity(entity);//设置参数
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(10000).build();
            httpPost.setConfig(requestConfig);
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(httpPost);//DefaultHttpClient的execute方法发送对应的请求
            String resultContent = new Utf8ResponseHandler().handleResponse(response);
            System.out.println("result=" + resultContent);
            return resultContent;

        } catch (Exception e) {
            System.out.println("url:" + url + ":" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * utf-8编码
     */
    static class Utf8ResponseHandler implements ResponseHandler<String> {
        public String handleResponse(final HttpResponse response)
                throws HttpResponseException, IOException {
            final StatusLine statusLine = response.getStatusLine();
            final HttpEntity entity = response.getEntity();
            if (statusLine.getStatusCode() >= 300) {//判断是否连接成功
                EntityUtils.consume(entity);//关闭资源，把底层的流给关闭
                throw new HttpResponseException(statusLine.getStatusCode(),
                        statusLine.getReasonPhrase());
            }
            return entity == null ? null : EntityUtils
                    .toString(entity, "UTF-8");//返回结果转换成字符串
        }
    }

    public static String sendGet(String url, String param) {
        String realUrl = url + param;
        System.out.println(realUrl);
        String rs = executeGet(realUrl);
        return rs;
    }

    public static String executePostIncludesHeader(String url, String body, String header) {
        try {
            HttpPost httpPost = new HttpPost(url);//httpPost请求
            StringEntity entity = new StringEntity(body, "UTF-8");//转换成字符串
            entity.setContentType("application/json");
            Header[] headers = new Header[]{
                    new BasicHeader("Authorization", header),
                    new BasicHeader("Content-Type", "application/json"),
                    new BasicHeader("Accept", "application/json")};
            httpPost.setEntity(entity);//设置参数
            httpPost.setHeaders(headers);
            httpPost.setEntity(entity);
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(httpPost);//DefaultHttpClient的execute方法发送对应的请求
            String resultContent = new Utf8ResponseHandler().handleResponse(response);
            System.out.println("result=" + resultContent);
            return resultContent;

        } catch (Exception e) {
            System.out.println("url:" + url + ":" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * access_token 接口直接调用，其它调用doGet
     */
    public static String executeGetIncHeader(String url, String header) {
        try {
            HttpGet httpGet = new HttpGet(url);
            Header[] headers = new Header[]{
                    new BasicHeader("Authorization", header),
                    new BasicHeader("Content-Type", "application/json"),
                    new BasicHeader("Accept", "application/json")};
            httpGet.setHeaders(headers);
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(httpGet);
            String resultContent = new Utf8ResponseHandler()
                    .handleResponse(response);
            System.out.println("result=" + resultContent);
            return resultContent;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static String executePutIncludesHeader(String url, String body, String header) {
        try {
            HttpPut httpPut = new HttpPut(url);//httpPut请求
            StringEntity entity = new StringEntity(body, "UTF-8");//转换成字符串
            entity.setContentType("application/json");
            Header[] headers = new Header[]{
                    new BasicHeader("Authorization", header),
                    new BasicHeader("Content-Type", "application/json"),
                    new BasicHeader("Accept", "application/json")};
            httpPut.setEntity(entity);//设置参数
            httpPut.setHeaders(headers);
            httpPut.setEntity(entity);
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(httpPut);//DefaultHttpClient的execute方法发送对应的请求
            String resultContent = new Utf8ResponseHandler().handleResponse(response);
            System.out.println("result=" + resultContent);
            return resultContent;

        } catch (Exception e) {
            System.out.println("url:" + url + ":" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    public static String executePost(String url, String body, String contentType) {
        try {
            HttpPost httpPost = new HttpPost(url);//httpPost请求
            StringEntity entity = new StringEntity(body, "UTF-8");//转换成字符串
            if (StringUtils.isEmpty(contentType)) {
                contentType = "application/json;charset=utf-8";
            }
            entity.setContentType(contentType);
            httpPost.setEntity(entity);//设置参数
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(10000).build();
            httpPost.setConfig(requestConfig);
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(httpPost);//DefaultHttpClient的execute方法发送对应的请求
            String resultContent = new Utf8ResponseHandler().handleResponse(response);
            System.out.println("result=" + resultContent);
            return resultContent;

        } catch (Exception e) {
            System.out.println("url:" + url + ":" + e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 构造cap-Basic Auth认证头信息
     *
     * @return
     */
    public static String getHeader(String shopCode, String psw, String authPre) {
        String auth = authPre + shopCode.toLowerCase() + ":" + psw;
//        System.out.print("[cap授权：]"+auth);
        byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("utf-8")));
        String authHeader = "Basic " + Base64.encodeBase64String(auth.getBytes());
        return authHeader;
    }

    /**
     * 执行post请求-参数格式form-data提交-中文会发生乱码-
     *
     * @param strUrl
     * @param params map<String,String>
     * @return
     */
    public static String excutePostByFormData(String strUrl, Map<String, String> params) {
        String boundary = "petx";
        String result = "";
        BufferedReader in = null;
        try {
            URL url = new URL(strUrl);
//            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            URLConnection urlConnection = url.openConnection();
//            urlConnection.setRequestMethod("POST");
            urlConnection.setRequestProperty("method", "POST");
            urlConnection.setConnectTimeout(30000);
            urlConnection.setReadTimeout(30000);
            urlConnection.setDoOutput(true);
            //设置通用请求属性为multipart/form-data
            urlConnection.setRequestProperty("content-type", "multipart/form-data;boundary=" + boundary);
            DataOutputStream dataOutputStream;
            dataOutputStream = new DataOutputStream(urlConnection.getOutputStream());

            for (String key : params.keySet()) {
                String value = params.get(key);
                //注意！此处是\r(回车：将当前位置移到本行开头)、\n(换行：将当前位置移到下行开头)要一起使用
                dataOutputStream.writeBytes("--" + boundary + "\r\n");
                dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + encode(key) + "\"\r\n");
                dataOutputStream.writeBytes("\r\n");
                //双重编码 -web解析会自动解码一层ISO-8859-1
                dataOutputStream.writeBytes(encode(encode(value)) + "\r\n");
            }
            //最后一个分隔符的结尾后面要跟"--"
            dataOutputStream.writeBytes("--" + boundary + "--");
            dataOutputStream.flush();
            dataOutputStream.close();
            InputStream inputStream = urlConnection.getInputStream();
            String line;
            in = new BufferedReader(new InputStreamReader(inputStream));
            while ((line = in.readLine()) != null) {
                result += line;
            }
            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return result;
    }


    private static String encode(String value) throws UnsupportedEncodingException {
        return URLEncoder.encode(value, "UTF-8");
    }

    /**
     * 执行post请求-参数格式form-data提交方式2-效率比上面的慢一倍，但是不会乱码=。=
     *
     * @param url
     * @param reqMap
     * @return
     */
    public static String excutePostFormData2(String url, Map<String, Object> reqMap) {
        String result = "";
        try {
            HttpPost post = new HttpPost(url);
            List<BasicNameValuePair> pairList = new ArrayList<BasicNameValuePair>();
            for (String key : reqMap.keySet()) {
                pairList.add(new BasicNameValuePair(key, reqMap.get(key) == null ? "" : reqMap.get(key).toString()));
            }
            UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(pairList, "UTF-8");
            post.setEntity(urlEncodedFormEntity);
            CloseableHttpClient httpClient = HttpClientBuilder.create().build();
            HttpResponse response = httpClient.execute(post);

            if (HttpStatus.SC_OK != response.getStatusLine().getStatusCode()) {
                throw new RuntimeException("接口连接失败");
            }
            result = EntityUtils.toString(response.getEntity(), "UTF-8");
//            System.out.println("调用接口结果："+result);

        } catch (Exception e) {
            throw new RuntimeException("接口连接失败:" + e.getMessage());
        }
        return result;
    }


}
